package impl.agentt.pEtu;

import java.util.ArrayList;
import java.util.logging.Logger;

import apps.BehTB;

import reservation.PlageHoraire;

import contraintes.ContrainteDispo;
import contraintes.Seance;
import debug.message.PEtuDebugText;
import fr.irit.smac.may.lib.components.messaging.receiver.AgentRef;
import fr.irit.smac.may.lib.interfaces.Push;
import fr.irit.smac.may.lib.pmbehaviour.PatternMatchingBehavior;
import message.EDTMessage;
import message.PresencePlacee;
import message.enseignant.DemandePresences;
import message.presence.DemandeInscriptionP;
import message.presence.DonneCritP;
import mysticedt.BehaviourP;

public class BehaviourPEtu extends BehaviourP {
	/**
	 * Reference vers l'agent Etudiant
	 */
	private AgentRef createur;
	/**
	 * Liste des indisponibilite de l'etudiant
	 */
	private ArrayList<ContrainteDispo> listIndisponibilite = new ArrayList<ContrainteDispo>();
	/**
	 * Seance dans laquelle la presence doit s'inscrire
	 */
	private Seance s;
	/**
	 * Plage Horaire dans laquelle la seance a ete reserve
	 */
	private PlageHoraire maPlageHoraire = null;
	/**
	 * Liste des agents pEns gerant cette presence
	 */
	private ArrayList<AgentRef> listPens = new ArrayList<AgentRef>();
	/**
	 * Criticite de l'agent pEtu.
	 */
	private Integer criticite = 0;
	
	PatternMatchingBehavior pmb = new PatternMatchingBehavior(this);
	
	public void defaultCase(Object message) {
		Logger log = Logger.getLogger("alerte");
		log.info("Alerte par "+this.getClass().getCanonicalName()+" : Incomprehension du message "+message.getClass().getCanonicalName());
	}

	/**
	 * Reception d'une demande d'initialisation
	 * - enregistrement des informations
	 * - lancement du mode recherche
	 */
	public void caseInitPresenceEtuAgent(Seance se, AgentRef c) {
		s = se;
		createur = c;
		debugText("Initialisation : OK - Createur : %s - Seance : %s",createur.getName(),s.getId());
		
		recherche();
	}
	
	/**
	 * Comportement de base d'un agent pEtu
	 */
	private void recherche() {
		debugText("Passage en mode recherche...");
		debugText("Demande a %s la presence s'occupant de la seance %s",s.getEnseignant().getName(),s.getId());
		send().send(new DemandePresences(myRef().pull(),s.getId()), s.getEnseignant());
	}

	/**
	 * Methode appelee lorsqu'un agent recoit un message de type DemandeCritP.
	 * 
	 * @param a
	 */
	// Un agent demande notre criticite
	public void caseDemandeCritP(AgentRef a) {
		send().send(new DonneCritP(myRef().pull(), criticite), a);
		// TODO retour au comportement nominal
	}

	/**
	 * Methode appelee lorsqu'un agent recoit un message de type DonneCritP.
	 * 
	 * @param a
	 */
	// Une presence noud donne sa criticite
	public void caseDonneCritP(AgentRef a, Integer i) {
		// TODO traiter l'info (si on a demande sa criticite a une autre
		// presence c'est surement pas pour rien
	}
	
	public void caseValiderInscriptionP(AgentRef a, PlageHoraire pH) {
		if(BehTB.plageHoraireIsInContrainteDispoListe(pH, listIndisponibilite)) {
			debugText("Placement : Impossible");
			parcoursPEns();
		} else {
			debugText("Placement : OK");
			debugText("Demande confirmation a %s",createur.getName());
			maPlageHoraire = pH;
			send().send(new PresencePlacee(myRef().pull(),maPlageHoraire), createur);
		}
	}
	
	public void caseValiderInscriptionPSansPh(AgentRef a) {
		debugText("Placement : Attente verification");
	}
	
	public void caseEnvoiePresence(ArrayList<AgentRef> listA) {
		listPens.clear();
		listPens.addAll(listA);
		debugText("Reception de la liste des %s reference(s)",listA.size());
		parcoursPEns();
	}
	
	private void parcoursPEns() {
		if(listPens.size()>0) {
			debugText("Demande inscription a %s",listPens.get(0).getName());
			send().send(new DemandeInscriptionP(myRef().pull(), criticite), listPens.remove(0));
		} else {
			debugText("Aucune des pEns ne convient");
			//TODO
		}
	}
	
	public void caseAcceptePlacement() {
		debugText("Placement : OK");
		criticite = 0;
	}
	
	public void caseRefusPlacement(ArrayList<ContrainteDispo> listCDisp) {
		debugText("Placement : Refuse");
		listIndisponibilite = listCDisp;
		//TODO se deinscrire
		recherche();
	}
	
	/*
	 * TODO comfirmation d'inscription a un cour
	 * caseConfInscrit
	 */

	/*
	 * TODO reception d'une notification de desincription a un cours, on repace
	 * en recherche caseLiberationPlace
	 */

	/*
	 * TODO le cours ou on ete inscrit n'est plus reserve (pEns a cede ca place
	 * a quelqu'un d'autre), on repace en recherche
	 */
	
	@Override
	protected Push<EDTMessage> cycle() {
		return new Push<EDTMessage>() {
			public void push(EDTMessage message) {
				pmb.match(message);
			}

		};
	}
	
	protected void debugText(String s , Object... params){
		if(debug().isDebugON()){
			debug().sendDebugMessage(new PEtuDebugText(myRef().pull(),String.format(s, params)));
		}
	}

}
